﻿using System.Linq;

namespace BorgExt.Behaviors
{
    public class SelectActivatedBehavior : Behavior<CompositionEventArgs>
    {
        public SelectActivatedBehavior(IRule<CompositionEventArgs> rule)
            : base(rule)
        { }

        public override void Activated(ExtensionEventArgs args)
        {
            if (BehaviorSlot != null)
            {
                var plug = args.Extension.Plugs[BehaviorSlot.Name];
                InternalAddCandidate(new CompositionEventArgs(BehaviorSlot, plug));
            }
            else
                foreach (var plug in args.Extension.Plugs)
                    foreach (var slot in plug.SlotsWherePlugged)
                        InternalAddCandidate(new CompositionEventArgs(slot, plug));
        }

        public override void Bind(Slot slot)
        {
            base.Bind(slot);

            foreach (var plug in slot.PluggedPlugs.Where(plug => plug.Extension.IsActivated))
                InternalAddCandidate(new CompositionEventArgs(slot, plug));
        }

        public override bool CanDeselect(CompositionEventArgs args, out LogEventArgs log)
        {
            if (!args.Plug.Extension.IsActivated)
            {
                log = null;
                return true;
            }

            return Rule.CanDecompose(args, out log);
        }

        public override bool CanSelect(CompositionEventArgs args, out LogEventArgs log)
        {
            if (!args.Plug.Extension.IsActivated)
            {
                log = new LogEventArgs(LogType.Info, "Contributor extension is not activated");
                return false;
            }

            return Rule.CanCompose(args, out log);
        }

        protected override void Compose(CompositionEventArgs args)
        {
            args.Slot.Select(args.Plug);
        }

        public override void Deactivated(ExtensionEventArgs args)
        {
            if (BehaviorSlot != null)
            {
                var plug = args.Extension.Plugs[BehaviorSlot.Name];
                Rule.RemoveCandidate(new CompositionEventArgs(BehaviorSlot, plug));
            }
            else
                foreach (var plug in args.Extension.Plugs)
                    foreach (var slot in plug.SlotsWherePlugged)
                        Rule.RemoveCandidate(new CompositionEventArgs(slot, plug));
        }

        protected override void Decompose(CompositionEventArgs args)
        {
            args.Slot.Deselect(args.Plug);
        }

        public override void Deselected(CompositionEventArgs args)
        {
            if (args.Plug.Extension.IsActivated)
                Rule.Decomposed(args);
        }

        public override void Deselecting(CompositionEventArgs args)
        {
            if (args.Plug.Extension.IsActivated)
                Rule.Decomposing(args);
        }

        private void InternalAddCandidate(CompositionEventArgs args)
        {
            Rule.AddCandidate(args);

            if (args.Slot.IsSelected(args.Plug))
                Rule.Composed(args);
        }

        public override void Plugged(CompositionEventArgs args)
        {
            if (args.Plug.Extension.IsActivated)
                InternalAddCandidate(args);
        }

        public override void Selected(CompositionEventArgs args)
        {
            if (args.Plug.Extension.IsActivated)
                Rule.Composed(args);
        }

        public override void Selecting(CompositionEventArgs args)
        {
            if (args.Plug.Extension.IsActivated)
                Rule.Composing(args);
        }

        public override void Unplugged(CompositionEventArgs args)
        {
            if (args.Plug.Extension.IsActivated)
                Rule.RemoveCandidate(args);
        }
    }
}

